企业级应用开发教程

1. Angular 简介和特性

1.1 什么是 Angular?

Angular 是一个由 Google 开发的开源前端框架,用于构建动态、单页应用(SPA)。它提供了强大的工具和库,帮助开发者快速构建复杂的企业级应用。

1.2 Angular 的主要特性

  • 组件化架构:Angular 应用由多个组件组成,每个组件负责特定的功能。
  • 双向数据绑定:自动同步视图和模型中的数据。
  • 依赖注入:简化组件和服务之间的依赖管理。
  • 模块化设计:通过模块组织代码,提高可维护性。
  • 强大的路由系统:支持复杂的导航和状态管理。

2. TypeScript 基础

2.1 什么是 TypeScript?

TypeScript 是 JavaScript 的超集,添加了静态类型检查和其他高级功能。Angular 使用 TypeScript 作为其主要编程语言。

2.2 TypeScript 基础语法

  • 变量声明:使用 let 和 const 声明变量。
  • 类型注解:通过 : type 指定变量类型。
  • 类和接口:支持面向对象编程。
let message: string = "Hello, TypeScript!";
console.log(message);

3. 环境搭建

3.1 安装 Node.js 和 npm

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,npm 是 Node.js 的包管理工具。

# 安装 Node.js
curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

# 验证安装
node -v
npm -v

3.2 安装 Angular CLI

Angular CLI 是一个命令行工具,用于快速生成 Angular 项目和组件。

# 安装 Angular CLI
npm install -g @angular/cli

# 验证安装
ng version

4. 第一个 Angular 应用

4.1 创建新项目

使用 Angular CLI 创建一个新的 Angular 项目。

ng new my-first-app
cd my-first-app

4.2 运行应用

启动开发服务器,查看应用运行情况。

ng serve --open

5. Angular 项目结构

5.1 项目目录结构

  • src/app:包含应用的主要代码。
  • src/assets:存放静态资源文件。
  • src/environments:包含不同环境的配置文件。

5.2 主要文件

  • app.module.ts:应用的根模块。
  • app.component.ts:应用的根组件。
  • index.html:应用的主 HTML 文件。

6. 组件创建和使用

6.1 创建组件

使用 Angular CLI 创建新组件。

ng generate component my-component

6.2 组件模板

组件的 HTML 模板定义了组件的视图。

<!-- my-component.component.html -->
<p>Hello from MyComponent!</p>

6.3 组件样式

组件的样式文件定义了组件的外观。

/* my-component.component.css */
p {
  color: blue;
}

7. 模板语法

7.1 插值表达式

使用双大括号 {{ }} 插入动态数据。

<p>{{ message }}</p>

7.2 属性绑定

使用方括号 [] 绑定 HTML 属性。

<img [src]="imageUrl">

8. 数据绑定

8.1 单向数据绑定

从组件到视图的数据绑定。

<p>{{ message }}</p>

8.2 双向数据绑定

使用 [(ngModel)] 实现双向数据绑定。

<input [(ngModel)]="message">

9. 生命周期钩子

9.1 常见生命周期钩子

  • ngOnInit:组件初始化时调用。
  • ngOnChanges:输入属性变化时调用。
  • ngOnDestroy:组件销毁时调用。
ngOnInit() {
  console.log('Component initialized');
}

10. 组件通信

10.1 父组件向子组件传递数据

使用 @Input 装饰器。

// 子组件
@Input() message: string;
<!-- 父组件 -->
<app-child [message]="parentMessage"></app-child>

10.2 子组件向父组件传递数据

使用 @Output 装饰器和 EventEmitter。

// 子组件
@Output() messageEvent = new EventEmitter<string>();

sendMessage() {
  this.messageEvent.emit('Hello from child');
}
<!-- 父组件 -->
<app-child (messageEvent)="receiveMessage($event)"></app-child>

11. 内置指令

11.1 ngIf

根据条件渲染元素。

<p *ngIf="isVisible">This is visible</p>

11.2 ngFor

循环渲染列表。

<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

11.3 ngSwitch

根据条件渲染不同内容。

<div [ngSwitch]="condition">
  <p *ngSwitchCase="'A'">Condition A</p>
  <p *ngSwitchCase="'B'">Condition B</p>
  <p *ngSwitchDefault>Default</p>
</div>

12. 属性指令

12.1 创建自定义属性指令

使用 Angular CLI 创建属性指令。

ng generate directive highlight

12.2 使用属性指令

在模板中使用自定义属性指令。

<p appHighlight>This text is highlighted</p>

13. 结构指令

13.1 创建自定义结构指令

使用 Angular CLI 创建结构指令。

ng generate directive unless

13.2 使用结构指令

在模板中使用自定义结构指令。

<p *appUnless="condition">This is shown when condition is false</p>

14. 自定义指令

14.1 创建自定义指令

使用 Angular CLI 创建自定义指令。

ng generate directive my-directive

14.2 使用自定义指令

在模板中使用自定义指令。

<p appMyDirective>This text is styled by my directive</p>

15. 服务创建和使用

15.1 创建服务

使用 Angular CLI 创建服务。

ng generate service my-service

15.2 注入服务

在组件中注入服务并使用。

constructor(private myService: MyService) {}

ngOnInit() {
  this.myService.getData().subscribe(data => {
    console.log(data);
  });
}

16. 依赖注入原理

16.1 依赖注入的概念

依赖注入是一种设计模式,用于管理对象之间的依赖关系。

16.2 提供者配置

在模块中配置服务提供者。

@NgModule({
  providers: [MyService]
})
export class AppModule {}

17. 服务的作用域

17.1 服务的作用域

服务可以在模块、组件或指令级别提供。

17.2 组件级别服务

在组件中提供服务。

@Component({
  providers: [MyService]
})
export class MyComponent {}

18. 路由配置

18.1 配置路由

在 app-routing.module.ts 中配置路由。

const routes: Routes = [
  { path: 'home', component: HomeComponent },
  { path: 'about', component: AboutComponent }
];

18.2 使用路由

在模板中使用路由链接。

<a routerLink="/home">Home</a>
<a routerLink="/about">About</a>

19. 路由参数

19.1 配置带参数的路由

在路由配置中定义参数。

const routes: Routes = [
  { path: 'user/:id', component: UserComponent }
];

19.2 获取路由参数

在组件中获取路由参数。

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this.route.params.subscribe(params => {
    console.log(params['id']);
  });
}

20. 子路由

20.1 配置子路由

在父组件中配置子路由。

const routes: Routes = [
  { path: 'parent', component: ParentComponent, children: [
    { path: 'child', component: ChildComponent }
  ]}
];

20.2 使用子路由

在父组件模板中使用子路由。

<router-outlet></router-outlet>

21. 路由守卫

21.1 创建路由守卫

使用 Angular CLI 创建路由守卫。

ng generate guard my-guard

21.2 配置路由守卫

在路由配置中使用守卫。

const routes: Routes = [
  { path: 'protected', component: ProtectedComponent, canActivate: [MyGuard] }
];

22. 惰性加载

22.1 配置惰性加载

在路由配置中使用惰性加载。

const routes: Routes = [
  { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];

22.2 创建惰性加载模块

使用 Angular CLI 创建惰性加载模块。

ng generate module lazy --route lazy --module app.module

23. 模板驱动表单

23.1 创建模板驱动表单

在模板中使用 ngModel 创建表单。

<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)">
  <input name="name" ngModel>
  <button type="submit">Submit</button>
</form>

23.2 处理表单提交

在组件中处理表单提交。

onSubmit(formValue: any) {
  console.log(formValue);
}

24. 响应式表单

24.1 创建响应式表单

在组件中使用 FormBuilder 创建表单。

constructor(private fb: FormBuilder) {}

myForm = this.fb.group({
  name: ['']
});

24.2 使用响应式表单

在模板中使用响应式表单。

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <input formControlName="name">
  <button type="submit">Submit</button>
</form>

25. 表单验证

25.1 内置验证器

使用内置验证器验证表单控件。

myForm = this.fb.group({
  name: ['', Validators.required]
});

25.2 自定义验证器

创建自定义验证器函数。

function validateName(control: AbstractControl): ValidationErrors | null {
  if (control.value.length < 3) {
    return { invalidName: true };
  }
  return null;
}

26. 动态表单

26.1 创建动态表单

在组件中动态生成表单控件。

myForm = this.fb.group({
  controls: this.fb.array([])
});

addControl() {
  this.controls.push(this.fb.control(''));
}

26.2 使用动态表单

在模板中使用动态表单。

<form [formGroup]="myForm">
  <div formArrayName="controls">
    <div *ngFor="let control of controls.controls; let i = index">
      <input [formControlName]="i">
    </div>
  </div>
  <button type="button" (click)="addControl()">Add Control</button>
</form>

27. HttpClient 模块

27.1 发送请求

使用 HttpClient 发送 HTTP 请求。

constructor(private http: HttpClient) {}

getData() {
  this.http.get('https://api.example.com/data').subscribe(data => {
    console.log(data);
  });
}

27.2 处理响应

处理 HTTP 响应数据。

getData() {
  this.http.get<MyData>('https://api.example.com/data').subscribe(data => {
    console.log(data.name);
  });
}

28. 拦截器

28.1 创建拦截器

使用 Angular CLI 创建拦截器。

ng generate interceptor my-interceptor

28.2 使用拦截器

在模块中配置拦截器。

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: MyInterceptor, multi: true }
  ]
})
export class AppModule {}

29. 错误处理

29.1 处理 HTTP 错误

在 HttpClient 请求中处理错误。

getData() {
  this.http.get('https://api.example.com/data').subscribe(
    data => console.log(data),
    error => console.error(error)
  );
}

29.2 全局错误处理

使用拦截器进行全局错误处理。

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return next.handle(req).pipe(
    catchError(error => {
      console.error(error);
      return throwError(error);
    })
  );
}

30. 缓存策略

30.1 使用缓存

在 HttpClient 请求中使用缓存。

getData() {
  this.http.get('https://api.example.com/data', { observe: 'response' }).subscribe(response => {
    if (response.ok) {
      localStorage.setItem('cachedData', JSON.stringify(response.body));
    }
  });
}

30.2 检查缓存

在请求前检查缓存数据。

getData() {
  const cachedData = localStorage.getItem('cachedData');
  if (cachedData) {
    console.log(JSON.parse(cachedData));
  } else {
    this.http.get('https://api.example.com/data').subscribe(data => {
      console.log(data);
    });
  }
}

31. Observable 和 Observer

31.1 Observable

Observable 是 RxJS 的核心概念,用于处理异步数据流。

const observable = new Observable(observer => {
  observer.next(1);
  observer.next(2);
  observer.complete();
});

31.2 Observer

Observer 是 Observable 的消费者,用于处理数据流。

observable.subscribe({
  next: value => console.log(value),
  complete: () => console.